/*
 * DestinationAdapter.java
 *
 * Created on September 6, 2006, 3:12 PM
 *
 * (C) 2006 R. Alexander Milowski
 */

package com.smallx.xproc.library;

import java.util.ArrayList;
import java.util.List;
import org.infoset.component.Component;
import org.infoset.xml.Item;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.Name;
import org.infoset.xml.Named;
import org.infoset.xml.XMLException;

/**
 *
 * @author alex
 */
public class DestinationAdapter implements ItemDestination {
   
   Name inputPort;
   Name outputPort;
   Component target;
   ItemDestination output;
   
   List<Name> elements;
   
   /** Creates a new instance of DestinationAdapter */
   public DestinationAdapter(Name outputPort, Name inputPort,Component target) {
      this.inputPort = inputPort;
      this.outputPort = outputPort;
      this.target = target;
      this.output = null;
      this.elements = new ArrayList<Name>();
   }
   
   public DestinationAdapter(Name outputPort,ItemDestination output) {
      this.inputPort = null;
      this.outputPort = outputPort;
      this.target = null;
      this.output = output;
      if (output==null) {
         throw new IllegalArgumentException("Output cannot be null for this constructor.");
      }
      this.elements = new ArrayList<Name>();
   }
   public void reset() {
      elements.clear();
      if (target!=null) {
         output = null;
      }
   }
   
   public Name getInputPort() {
      return inputPort;
   }
   
   public Name getOutputPort() {
      return outputPort;
   }
   
   public void send(Item item)
      throws XMLException
   {
      if (output==null) {
         output = target.getInputPort(inputPort);
      }
      switch (item.getType()) {
         case ElementItem:
            elements.add(((Named)item).getName());
            break;
         case ElementEndItem:
            Name nm = ((Named)item).getName();
            if (elements.size()==0) {
               throw new XMLException("("+outputPort+" -> "+inputPort+") Unbalanced event stream: end tag "+nm+" received after document end.");
            }
            Name top = elements.remove(elements.size()-1);
            if (!nm.equals(top)) {
               throw new XMLException("("+outputPort+" -> "+inputPort+") Unbalanced event stream: end tag "+nm+" does not match start tag "+top);
            }
      }
      output.send(item);
   }
   
}
